﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

using ITAP.ContourBuilder.Components;
using ITAP.ContourBuilder.Components.Dimensions;
using ITAP.Core.Modelling;

namespace ITAP.ContourBuilder.Manipulation
{
    public class CommandMoveComponents : SerializedCommand
    {
        private List<Type> acceptedTypesToMove = null;
        private Point prevMousePoint;
        private Point startMousePoint;
        private ModelPoint mouseDownPoint = null;

        public CommandMoveComponents(ContourControl control)
            : base(control)
        {
        }

        public CommandMoveComponents(ContourControl control, Type[] acceptedTypesToMove)
            : this(control)
        {
            this.acceptedTypesToMove = new List<Type>(acceptedTypesToMove);
        }

        bool isInTolerance = false;
        int counter = 0;
        bool isMoved = false;
        public override void ObtainPeripheryState(GlobalPeripheryState state)
        {
      //      counter++;
            base.ObtainPeripheryState(state);

            if (state.MouseState.MouseMode == MouseMode.Down && state.MouseState.State.Button == System.Windows.Forms.MouseButtons.Left)
            {
                isInTolerance = false;
                prevMousePoint = state.MouseState.State.Location;
                startMousePoint = prevMousePoint;
                mouseDownPoint = this.ScreenPointToModelPoint(state.MouseState.State.Location);

                foreach (IContourComponent selectedComponent in control.ContourContainer.SelectedComponentsStack)
                    if (selectedComponent.IsInTolerance(mouseDownPoint, 2))
                    {
                        isInTolerance = true;
                        break;
                    }
            }
            else if (state.MouseState.MouseMode == MouseMode.Move && state.MouseState.State.Button == System.Windows.Forms.MouseButtons.Left)
            {
                ModelPoint startPoint = this.ScreenPointToModelPoint(prevMousePoint);
                ModelPoint endPoint = this.ScreenPointToModelPoint(state.MouseState.State.Location);

                ModelVector vector = new ModelVector(startPoint, endPoint);

                // Если двигаем компонент с ненулевым смещением, то нужно сохранить предыдущее состояние компонента 
                // для возможности выполнения отмены перемещения.                
                if (this.savedToHistory)
                {
                    this.undoContainer = this.control.ContourContainer.Clone() as ContourContainer;
                    this.savedToHistory = false;
                }

                //lock (control.ContourContainer)
                {
                    foreach (IContourComponent selectedComponent in control.ContourContainer.SelectedComponentsStack)
                    {
                        
                        if (!(selectedComponent is Dimension) && !this.acceptedTypesToMove.Contains(selectedComponent.GetType()))
                            continue;

                        if (!(selectedComponent.Parent is ContourContainer))
                        {
                            ContourModel rootModel = selectedComponent.GetRootModel();
                            bool isInBbox = control.ContourContainer.InnerBoundingBox.Contains(rootModel.BoundingBox);

                            if (vector.Length != 0)
                                isMoved = true;

                            selectedComponent.MoveWithOffset(vector);
                            selectedComponent.Modified = true;
                            control.ContourContainer.Update();

                            ModelVector backVector = vector.Rotate(new Angle(Math.PI));

                            if (control.ContourContainer.HasBounds && !control.ContourContainer.InnerBoundingBox.Contains(rootModel.BoundingBox))
                            {
                                selectedComponent.MoveWithOffset(backVector);
                                control.ContourContainer.Update();
                            }
                        }
                        else
                        {
                            selectedComponent.MoveWithOffset(vector);
//                            selectedComponent.Modified = true;
                            control.ContourContainer.Update();
                        }
                    }

                    prevMousePoint = state.MouseState.State.Location;
                }
            }

            else if (state.MouseState.MouseMode == MouseMode.Up &&
                state.MouseState.State.Button == System.Windows.Forms.MouseButtons.Left &&
                startMousePoint != state.MouseState.State.Location)
            {
                if (isMoved)
                {
                    isMoved = false;
                    this.SaveToHistory();
                    this.control.ToleranceManager.Visit(this.control.ContourContainer);
                    this.control.Invalidate();
                }

            }

        //    counter--;            
        //    Console.WriteLine(counter);

        }

        public override string ToString()
        {
            return "Перемещение компонент";
        }

        private bool savedToHistory = false;
        public override void SaveToHistory()
        {
            base.SaveToHistory();
            this.savedToHistory = true;
            //    Console.WriteLine("SaveToHistory()");
        }

        public override object Clone()
        {
            CommandMoveComponents clone = (CommandMoveComponents)base.Clone();
            clone.acceptedTypesToMove = new List<Type>(this.acceptedTypesToMove);
            return clone;
        }
    }
}
